package com.dd.cloud.user.service.agent.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.AgentConstants;
import com.dd.cloud.common.constants.HealthConstants;
import com.dd.cloud.user.entity.agent.Agent;
import com.dd.cloud.user.entity.agent.AgentUser;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.mapper.agent.AgentMapper;
import com.dd.cloud.user.mapper.agent.AgentUserMapper;
import com.dd.cloud.user.req.agent.*;
import com.dd.cloud.user.res.agent.AgentUserLoginRes;
import com.dd.cloud.user.service.agent.IAgentUserService;
import com.dd.cloud.common.config.servlet.JwtUtils;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.config.sms.SmsComponent;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.CodecUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;

/**
 * @author Lx
 * @version 1.0
 */
@Slf4j
@Service
public class AgentUserServiceImpl extends ServiceImpl<AgentUserMapper, AgentUser> implements IAgentUserService {
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private AgentMapper agentMapper;
    @Autowired
    private SmsComponent smsComponent;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 代理商用户登录 密码方式
     *
     * @param request
     * @param response
     * @param req
     * @return
     */
    @Override
    public AgentUserLoginRes loginAgentUserPwd(HttpServletRequest request, HttpServletResponse response, AgentUserLoginPwdReq req) {
        QueryWrapper<AgentUser> qw = new QueryWrapper<>();
        qw.lambda().eq(AgentUser::getAccount, req.getAccount());
        qw.lambda().ne(AgentUser::getStatus, AgentConstants.AgentUserStatus.DEL);
        AgentUser agentUser = getOne(qw);
        if (agentUser == null) {
            throw new ZekeException(400, "代理商不存在");
        }
        String password = CodecUtils.md5Hex(req.getPwd(), agentUser.getSalt());
        if (!password.equals(agentUser.getPassword())) {
            throw new ZekeException(400, "账号或密码错误");
        }
        Agent agent = agentMapper.selectById(agentUser.getAgentId());
        if (agent.getStatus() != AgentConstants.AgentStatus.NORMAL) {
            throw new ZekeException(400, "代理商非正常使用状态");
        }
        AgentUserLoginRes res = new AgentUserLoginRes();
        BeanUtils.copyProperties(agentUser, res);
        jwtUtils.createToken(new LoginInfo(agentUser.getId(), agentUser.getAgentId(), LoginInfo.UserType.AGENT, agentUser.getName(), jwtUtils.getUserAgent(request)), request, response);
        return res;
    }

    /**
     * 代理商用户登录 验证码方式
     *
     * @param request
     * @param response
     * @param req
     * @return
     */
    @Override
    public AgentUserLoginRes loginAgentUserCode(HttpServletRequest request, HttpServletResponse response, AgentUserLoginCodeReq req) {
        smsComponent.verifyPhoneCode(req.getPhone(), req.getCode());
        QueryWrapper<AgentUser> qw = new QueryWrapper<>();
        qw.lambda().eq(AgentUser::getPhoneNum, req.getPhone());
        qw.lambda().ne(AgentUser::getStatus, AgentConstants.AgentUserStatus.DEL);
        AgentUser agentUser = getOne(qw);
        if (agentUser == null) {
            throw new ZekeException(400, "代理商不存在");
        }
        Agent agent = agentMapper.selectById(agentUser.getAgentId());
        if (agent.getStatus() != AgentConstants.AgentStatus.NORMAL) {
            throw new ZekeException(400, "代理商非正常使用状态");
        }
        AgentUserLoginRes res = new AgentUserLoginRes();
        BeanUtils.copyProperties(agentUser, res);
        jwtUtils.createToken(new LoginInfo(agentUser.getId(), agentUser.getAgentId(), LoginInfo.UserType.AGENT, agentUser.getName(), jwtUtils.getUserAgent(request)), request, response);
        return res;
    }

    /**
     * 代理商用户找回密码
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void forgetPwdAgentUser(AgentUserForgetPwdReq req) {
        if (!req.getPwd().equals(req.getPwds())) {
            throw new ZekeException(400, "两次密码不一致");
        }
        smsComponent.verifyPhoneCode(req.getPhone(), req.getCode());
        QueryWrapper<AgentUser> qw = new QueryWrapper<>();
        qw.lambda().eq(AgentUser::getPhoneNum, req.getPhone());
        qw.lambda().ne(AgentUser::getStatus, AgentConstants.AgentUserStatus.DEL);
        AgentUser agentUser = getOne(qw);
        if (agentUser == null) {
            throw new ZekeException(400, "代理商不存在");
        }
        AgentUser update = new AgentUser();
        update.setId(agentUser.getId());
        update.setSalt(CodecUtils.generateSalt());
        update.setPassword(CodecUtils.md5Hex(req.getPwd(), update.getSalt()));
        update.setUpdateDate(LocalDateTime.now());
        updateById(update);
        redisTemplate.opsForValue().set(HealthConstants.ClientType.HEALTHAGENT + agentUser.getAgentId() + "-" + agentUser.getId() + "-" + LoginInfo.UserType.AGENT, "loginOut");
    }

    /**
     * 代理商用户通过旧密码修改密码
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAgentUser(AgentUserUpdatePwdReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.AGENT).get();
        if (!req.getPwd().equals(req.getPwds())) {
            throw new ZekeException(400, "两次密码不一致");
        }
        AgentUser agentUser = getById(loginInfo.getId());
        if (agentUser == null || agentUser.getStatus() == AgentConstants.AgentUserStatus.DEL) {
            throw new ZekeException(400, "代理商不存在");
        }
        String password = CodecUtils.md5Hex(req.getOldPwd(), agentUser.getSalt());
        if (!password.equals(agentUser.getPassword())) {
            throw new ZekeException(400, "旧密码不正确");
        }
        AgentUser update = new AgentUser();
        update.setId(agentUser.getId());
        update.setSalt(CodecUtils.generateSalt());
        update.setPassword(CodecUtils.md5Hex(req.getPwd(), update.getSalt()));
        update.setUpdateDate(LocalDateTime.now());
        updateById(update);
        redisTemplate.opsForValue().set(HealthConstants.ClientType.HEALTHAGENT + agentUser.getAgentId() + "-" + agentUser.getId() + "-" + LoginInfo.UserType.AGENT, "loginOut");
    }

    /**
     * 初始化代理商用户
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initAgentUser(AgentCreateReq req) {
        AgentUser agentUser = new AgentUser();
        agentUser.setName(req.getName());
        agentUser.setAgentId(req.getAgentId());
        agentUser.setAccount(req.getPhoneNum());
        agentUser.setPhoneNum(req.getPhoneNum());
        agentUser.setEmail(req.getEmail());
        agentUser.setSalt(CodecUtils.generateSalt());
        agentUser.setPassword(CodecUtils.md5Hex(req.getPhoneNum().substring(5), agentUser.getSalt()));
        agentUser.setStatus(AgentConstants.AgentUserStatus.NORMAL);
        agentUser.setCreateDate(LocalDateTime.now());
        save(agentUser);
    }
}
